package main

import (
	"encoding/csv"
	"fmt"
	"log"
	"net/http"
	"os"
	"strings"

	"github.com/PuerkitoBio/goquery"
)

var textMap map[string]Text = make(map[string]Text)

type Text struct {
	Text   string // 文字
	Href   string // 链接
	Book   string // 书籍
	Course string // 课程
}

func main() {
	// 创建文件
	csvFile, err := os.Create("texts.csv")
	if err != nil {
		log.Fatalf("failed creating file: %s", err)
	}
	defer csvFile.Close()
	csvWriter := csv.NewWriter(csvFile)
	defer csvWriter.Flush()

	// 写入内容
	urls := urls()
	for _, url := range urls {
		err, texts := query(url)
		if err != nil {
			//log.Printf("error: %s, %s", url, err.Error())
			continue
		}

		for _, text := range texts {
			fmt.Printf("%s, %s, %s, %s\n", text.Text, text.Href, text.Book, text.Course)
			textMap[text.Text] = text
		}
	}

	// 写入 CSV
	for _, text := range textMap {
		_ = csvWriter.Write([]string{text.Text, text.Href, text.Book, text.Course})
	}
}

// urls 生成待验证URL
func urls() (urls []string) {
	for i := 1; i <= 600; i++ {
		urls = append(urls, fmt.Sprintf("https://www.topath.net.cn/smbsop/%d.html", i))
	}

	return urls
}

// query 查询目标元素
func query(url string) (err error, texts []Text) {
	// 请求 HTML 页面
	res, err := http.Get(url)
	if err != nil {
		log.Printf("error: %s, %s", url, err.Error())
		return err, nil
	}
	defer res.Body.Close()

	if res.StatusCode != 200 {
		return fmt.Errorf("status code error: %d %s", res.StatusCode, res.Status), nil
	}

	// 加载 HTML 内容
	doc, err := goquery.NewDocumentFromReader(res.Body)
	if err != nil {
		log.Printf("error: %s, %s", url, err.Error())
		return err, nil
	}

	// 查找目标元素
	doc.Find(".writemenu").Each(func(i int, s *goquery.Selection) {
		b := s.Find(".writemenu_sub").Text()
		c := s.Find(".writemenu_title").Text()

		// 查找文字列表
		s.Find(".writemenu_listA").Each(func(i int, s *goquery.Selection) {
			t := s.Text()
			h, _ := s.Attr("href")
			text := Text{
				Text:   strings.Join(strings.Fields(t), ""),
				Href:   h,
				Book:   b,
				Course: c,
			}

			texts = append(texts, text)
		})
	})

	return nil, texts
}
